package cn.cxq.learning.e3_1;

public class LnUtil {
    private static final double LOGTWO = 0.69314718055994531;

    private static final double ZERO = 0.5E-100;

    private static int getLogItemNumber(double a) {
        int N;
        if (a <= 1) N = -1;
        else if (a <= 1.2) N = 7;
        else if (a <= 1.5) N = 10;
        else if (a <= 2.0) N = 15;
        else if (a <= 3.0) N = 24;
        else if (a <= 10) N = 84;
        else N = 84 * (int) (a / 10);
        return N;
    }

    private static double logTV(double a) {
        int N = 0, K, NK;
        double x, xx, y;
        x = (a - 1) / (a + 1);
        xx = x * x;
        N = getLogItemNumber(a);
        NK = N * 2 + 1;
        y = 1.0 / NK;
        for (K = N; K > 0; K--) {
            NK -= 2;
            y = 1.0 / NK + xx * y;
        }
        return 2.0 * x * y;
    }

    public static double log(double a) {
        int TYPE = 0, K = 0;
        double x0, x, y, power = 2.0;
        x = a;
        if (x < ZERO) return -100;
        if (x < 1) {
            x = 1.0 / x;
            TYPE = 1;
        }
        while (power < x) {
            power *= 2.0;
            K++;
        }
        y = logTV(2.0 * x / power) + K * LOGTWO;
        if (TYPE == 1) y = -y;
        return y;
    }
}
